/***
 * @Description:本文件是用来定义网络数据包的格式，数据类型，数据包的链表内存空间分布的C语言文件
 * @Author: Liverpool
 * @Date: 2024-03-20 02:06:26
 * @LastEditTime: 2024-03-21 00:39:33
 * @LastEditors: Liverpool
 */
#include "packet.h"
#include "tools.h"
// 定于预留数据变量
static D_Locker locker;
static D_PacketBlock block_buffer[Packet_PacketBlock_Cnt]; // 协议栈可以使用的数据块个数
static D_MemoryBlock block_list;                           // 定义用来管理的数据块的内存管理链表
static D_Packet packet_buffer[Packet_Packet_Cnt];          // 协议栈可以使用的数据包个数
static D_MemoryBlock packet_list;                          // 定义用来管理数据包的内存管理链表

/***
 * @description: 得到当前数据包的pos以后还有多少的剩余空间
 * @Author: Liverpool
 * @Date: 2024-04-10 23:53:31
 * @return {*} pos位置后的数据包剩余空间
 * @param {D_Packet} *packet 需要查找的数据包内存地址
 */
static inline int total_packet_remain(D_Packet *packet)
{
    return packet->total_size - packet->pos;
}

/***
 * @description: 得到当前数据包的pos位置的数据块还有多少剩余空间
 * @Author: Liverpool
 * @Date: 2024-04-11 00:27:52
 * @return {*} pos位置的数据块还有多少剩余空间
 * @param {D_Packet} *packet 需要查找的数据包内存地址
 */
static inline int current_packet_packetBlock_remain(D_Packet *packet)
{
    D_PacketBlock *block = packet->curr_block;
    if (!block)
        return 0;
    return (int)(packet->curr_block->data + block->size - packet->block_offset);
}

/***
 * @description: 用于计算数据块最后还剩余的内存空间
 * @Author: Liverpool
 * @Date: 2024-04-10 23:49:30
 * @return {*} 当前数据块剩余的空间
 * @param {D_PacketBlock} *packet_block 需要进行查找的数据块内存地址
 */
static inline int packetBlock_tail_free(D_PacketBlock *packet_block)
{
    return (int)((packet_block->payload + Packet_PacketBlock_Size) - (packet_block->data + packet_block->size));
}
#if Debug_Display_Enable(Debug_Packet)
/***
 * @description: 用于显示和检查数据包的数据内容
 * @Author: Liverpool
 * @Date: 2024-03-26 23:55:46
 * @return {*}
 * @param {D_Packet} *packet 需要显示和检查的数据包地址
 */
static void display_check_packet(D_Packet *packet)
{
    if (!packet) // 数据包为空
    {
        debug_error(Debug_Packet, "invalid packet,packet == Null");
        return;
    }
    debug_info(Debug_Packet, "check packet %p: size %d", packet, packet->total_size); // 打印数据包容量大小
    D_PacketBlock *curr;
    int index = 0;
    int total_size = 0;
    for (curr = packet_first_packetBlock(packet); curr; curr = packetBlock_list_next(curr))
    {
        // 对数据存储在缓存中的存储位置进行判断
        // if ((curr->data < curr->payload) || (curr->data >= curr->payload + Packet_PacketBlock_Size))
        // {
        //     debug_error(Debug_Packet, "bad packetBlock data");
        // }
        int pre_size = (int)(curr->data - curr->payload); // 得到数据块存储前缓存的大小
        int used_size = curr->size;                       // 得到数据块的大小
        int free_size = packetBlock_tail_free(curr);      // 数据块存储后的缓存大小
        debug_info(Debug_Packet, "%d: pre:%d byte, used:%d byte, free:%d byte", index++, pre_size, used_size, free_size);
        int block_size = pre_size + used_size + free_size; // 得到整个数据块的整个缓存容量
        if (block_size != Packet_PacketBlock_Size)
        {
            debug_error(Debug_Packet, "bad packetBlock size: %d != %d", block_size, Packet_PacketBlock_Size);
        }
        total_size += used_size;
    }
    if (total_size != packet->total_size)
    {
        debug_error(Debug_Packet, "bad packet size: %d != %d", total_size, packet->total_size);
    }
}
#else
#define display_check_packet(packet)
#endif

/***
 * @description: 对于整个网络数据包这个模块文件进行初始化
 * @Author: Liverpool
 * @Date: 2024-03-21 00:40:17
 * @return {*}
 */
net_err_t packet_model_init(void)
{
    debug_info(Debug_Packet, "init packet model...");
    locker_init(&locker, Locker_Thread);                                                                      // 初始化网络数据包的锁
    memory_block_init(&block_list, block_buffer, sizeof(D_PacketBlock), Packet_PacketBlock_Cnt, Locker_Self); // 初始化数据块内存管理链表
    memory_block_init(&packet_list, packet_buffer, sizeof(D_Packet), Packet_Packet_Cnt, Locker_Self);         // 初始化数据包内存管理链表
    debug_info(Debug_Packet, "init packet model done...");
    return NET_ERR_OK;
}
/***
 * @description: (内部函数)从数据块内存管理链表中分出一个数据块
 * @Author: Liverpool
 * @Date: 2024-03-24 19:43:59
 * @return {*} 分配得到的数据块内存地址
 */
static D_PacketBlock *packetBlock_alloc(void)
{
    locker_lock(&locker);
    D_PacketBlock *block = (D_PacketBlock *)memory_block_alloc(&block_list, -1);
    locker_Unlock(&locker);
    if (block) // 如果分配成功
    {
        // 初始化刚分配的数据块
        block->size = 0;
        block->data = (uint8_t *)0;
        list_node_init(&block->node);
    }
    return block;
}
/***
 * @description: 释放数据块的节点
 * @Author: Liverpool
 * @Date: 2024-03-30 17:30:07
 * @return {*}
 * @param {D_PacketBlock} *block 需要释放的数据块节点的地址
 */
static void packetBlock_free(D_PacketBlock *block)
{
    locker_lock(&locker);
    memory_block_free(&block_list, block);
    locker_Unlock(&locker);
}
/***
 * @description: 释放数据块链表
 * @Author: Liverpool
 * @Date: 2024-03-28 02:41:42
 * @return {*}
 * @param {D_PacketBlock} *block 需要释放的数据块链表的头结点
 */
static void packetBlock_free_list(D_PacketBlock *block)
{
    while (block)
    {
        D_PacketBlock *next = packetBlock_list_next(block);
        packetBlock_free(block);
        block = next;
    }
}
/***
 * @description: (内部函数)在数据包内构建数据块的链表
 * @Author: Liverpool
 * @Date: 2024-03-24 19:39:08
 * @return {*} 返回数据块链表的第一个结点
 * @param {int} size 需要分配的数据块的内存大小
 * @param {int} insterionMode 数据块链表的分配方式(头插法 or 尾插法)
 */
static D_PacketBlock *packetBlock_alloc_list(int size, int insterionMode)
{
    D_PacketBlock *first_block = (D_PacketBlock *)0; // 链表中的第一个数据块内存地址
    D_PacketBlock *prev_block = (D_PacketBlock *)0;  // 记录链表中的上一个数据块地址
    int curr_size = 0;
    while (size)
    {
        D_PacketBlock *new_block = packetBlock_alloc();
        if (!new_block) // 数据块没有分配成功
        {
            debug_error(Debug_Packet, "no packetBlock to alloc(%d)", size);
            // 需要释放已经分配好的数据块
            if (first_block)
            {
                packetBlock_free_list(first_block);
            }
            return (D_PacketBlock *)0;
        }
        // 构建数据块链表
        if (insterionMode == PacketBlock_Insertion_Head) // 头插法
        {
            curr_size = size > Packet_PacketBlock_Size ? Packet_PacketBlock_Size : size; // 得到需要在数据块中分配的数据容量大小
            new_block->size = curr_size;
            new_block->data = new_block->payload + Packet_PacketBlock_Size - curr_size;
            if (first_block)
            {
                list_node_set_next(&new_block->node, &first_block->node); // 在上一个数据块的链表头部插入新链表
            }
            first_block = new_block;
        }
        else // 尾插法
        {
            if (!first_block)
            {
                first_block = new_block; // 如果首结点为空，那就分配数据块结点
            }
            curr_size = size > Packet_PacketBlock_Size ? Packet_PacketBlock_Size : size; // 得到需要在数据块中分配的数据容量大小
            new_block->size = curr_size;
            new_block->data = new_block->payload;
            if (prev_block)
            {
                list_node_set_next(&prev_block->node, &new_block->node); // 构建数据块链表
            }
        }
        size -= curr_size;
        prev_block = new_block;
    }
    return first_block;
}
/***
 * @description: (内部函数)把数据块链表插入到数据包中
 * @Author: Liverpool
 * @Date: 2024-03-26 01:15:20
 * @return {*}
 * @param {D_Packet} *packet 需要插入的数据包
 * @param {D_PacketBlock} *first_block 数据块链表的头结点
 * @param {int} insertMode 数据块链表插入的方法(头插法 or 尾插法)
 */
static void packet_insert_packetBlockList(D_Packet *packet, D_PacketBlock *first_block, int insertMode)
{
    if (insertMode) // 尾插法
    {
        while (first_block) // 把数据块链表一个个结点都插入到数据包链表头中
        {
            D_PacketBlock *next_block = packetBlock_list_next(first_block);
            list_insert_last(&packet->block_list, &first_block->node);
            packet->total_size += first_block->size; // 计算数据包总容量
            first_block = next_block;
        }
    }
    else // 头插法的实现
    {
        D_PacketBlock *pre = (D_PacketBlock *)0;
        while (first_block)
        {
            D_PacketBlock *next_block = packetBlock_list_next(first_block);
            if (pre)
            {
                // 如果前面有结点插入那就需要插入在前结点之后
                list_insert_after(&packet->block_list, &pre->node, &first_block->node);
            }
            else
            {
                // 如果没有节点插入，那就需要把新的数据链表的头结点插入到数据包的数据块链表头部
                list_insert_first(&packet->block_list, &first_block->node);
            }
            packet->total_size += first_block->size; // 计算数据包总容量
            pre = first_block;
            first_block = next_block;
        }
    }
}

/***
 * @description: 分配固定大小的数据包
 * @Author: Liverpool
 * @Date: 2024-03-24 19:16:19
 * @return {*} 返回分配好的数据包的内存地址
 * @param {int} size 需要分配的数据包内存大小
 */
D_Packet *packet_alloc(int size)
{
    locker_lock(&locker);
    D_Packet *packet = (D_Packet *)memory_block_alloc(&packet_list, -1); // 分配一个数据包
    locker_Unlock(&locker);
    if (!packet) // 数据包没有分配成功
    {
        debug_error(Debug_Packet, "no packet buffer");
        return (D_Packet *)0;
    }
    // 对数据包的内容进行初始化
    packet->total_size = 0;
    packet->ref = 1;
    list_init(&packet->block_list); // 初始化数据块链表的头结点
    list_node_init(&packet->node);  // 初始化数据包链表结点
    if (size)
    {
        D_PacketBlock *head_block = packetBlock_alloc_list(size, PacketBlock_Insertion_Head);
        if (!head_block)
        {
            locker_lock(&locker);
            memory_block_free(&packet_list, packet); // 释放数据包内存空间
            locker_Unlock(&locker);
            return (D_Packet *)0;
        }
        // 数据包链接数据块链表
        packet_insert_packetBlockList(packet, head_block, Packet_PacketBlkList_Tail); // 使用尾插法
    }
    packet_reset_access(packet);
    display_check_packet(packet); // 显示打印数据包内容
    return packet;
}

/***
 * @description:对数据包内存进行释放
 * @Author: Liverpool
 * @Date: 2024-03-28 02:36:59
 * @return {*}
 * @param {D_Packet} *packet 需要释放的数据包地址
 */
void packet_free(D_Packet *packet)
{
    locker_lock(&locker);
    if (--packet->ref == 0)
    {
        packetBlock_free_list(packet_first_packetBlock(packet)); // 释放数据包中的数据块链表
        memory_block_free(&packet_list, packet);                 // 释放数据包内存空间
    }
    locker_Unlock(&locker);
}

/***
 * @description: 在数据包前面添加包头
 * @Author: Liverpool
 * @Date: 2024-03-29 00:23:12
 * @return {*} 添加包头中的错误
 * @param {D_Packet} *packet 需要添加包头的数据包地址
 * @param {int} size 需要添加包头的内存大小
 * @param {int} continuousMode 添加的包头是否连续
 */
net_err_t packet_add_header(D_Packet *packet, int size, int continuousMode)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    D_PacketBlock *packetBlock = packet_first_packetBlock(packet);   // 得到数据块链表的第一个节点
    int resv_size = (int)(packetBlock->data - packetBlock->payload); // 得到缓存中前面的剩余空间
    if (size <= resv_size)
    {
        // 如果添加的数据包内存空间小于剩余的缓存空间，那就直接加入到数据存储前面
        packetBlock->size += size;
        packetBlock->data -= size; // 定位新的数据存储位置
        packet->total_size += size;
        display_check_packet(packet);
        return NET_ERR_OK;
    }
    // 数据块存储区前的缓存不够添加数据头
    if (continuousMode == Packet_Header_Continuous)
    {
        // 添加的数据包是连续的
        if (size > Packet_PacketBlock_Size)
        {
            // 添加的数据包尺寸过大
            debug_error(Debug_Packet, "Add packetHeader,size too big: %d > %d", size, Packet_PacketBlock_Size);
            return NET_ERR_SIZE;
        }
        packetBlock = packetBlock_alloc_list(size, Packet_PacketBlkList_Head); // 使用头插法构建一个数据块链表
        if (!packetBlock)
        {
            debug_error(Debug_Packet, "no packetBlock (size:%d)", size);
            return NET_ERR_NONE;
        }
    }
    else
    {
        // 添加的数据包头是不连续的
        // 先把当前数据块节点的缓存空间用完
        packetBlock->data = packetBlock->payload;
        packetBlock->size += resv_size;
        packet->total_size += resv_size;
        size -= resv_size;
        // 再把剩余的需要分配的头部空间构建成一个数据块链表
        packetBlock = packetBlock_alloc_list(size, Packet_PacketBlkList_Head); // 使用头插法构建一个数据块链表
        if (!packetBlock)
        {
            debug_error(Debug_Packet, "no packetBlock (size:%d)", size);
            return NET_ERR_NONE;
        }
    }
    packet_insert_packetBlockList(packet, packetBlock, PacketBlock_Insertion_Head); // 使用头插法把数据包的数据块链表插入在原数据块链表之前
    display_check_packet(packet);
    return NET_ERR_OK;
}

/***
 * @description: 在数据包头部移除固定容量的包头
 * @Author: Liverpool
 * @Date: 2024-03-30 14:33:25
 * @return {*} 移除过程中的错误
 * @param {D_Packet} *packet 需要移除的数据包的内存地址
 * @param {int} size 要移除的数据包的包头容量
 */
net_err_t packet_remove_header(D_Packet *packet, int size)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    D_PacketBlock *block = packet_first_packetBlock(packet); // 得到数据包中的第一个数据块节点
    while (size)
    {
        D_PacketBlock *next_block = packetBlock_list_next(block);
        if (size < block->size)
        {
            // 需要移除的包头尺寸小于当前数据块的存储容量，那就直接移除
            block->data += size; // 直接定位到包头移除后的数据存储地址
            block->size -= size;
            packet->total_size -= size;
            size = 0;
            break;
        }
        int current_size = block->size;
        list_remove_first(&packet->block_list); // 移除数据包中的数据块链表的第一个节点
        packetBlock_free(block);
        size -= current_size;
        packet->total_size -= current_size;
        block = next_block;
    }
    display_check_packet(packet);
    return NET_ERR_OK;
}

/***
 * @description: 数据包重新定义内存空间容量尺寸
 * @Author: Liverpool
 * @Date: 2024-03-31 00:25:28
 * @return {*} 在重新调整容量过程中的错误
 * @param {D_Packet} *packet 需要进行重新调整的数据包的内存地址
 * @param {int} to_size 需要重新调整成为的内存空间容量
 */
net_err_t packet_resize(D_Packet *packet, int to_size)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    if (to_size == packet->total_size)
    {
        return NET_ERR_OK; // 如果需要调整的容量等于现在数据包的容量那就不需要调整直接返回就行了
    }
    if (packet->total_size == 0)
    {
        // 本来数据包中没有分配数据块链表，那就直接分配一个数据块链表
        D_PacketBlock *block = packetBlock_alloc_list(to_size, PacketBlock_Insertion_Tail);
        if (!block)
        {
            debug_error(Debug_Packet, "no blovk");
            return NET_ERR_MEMORY;
        }
        packet_insert_packetBlockList(packet, block, Packet_PacketBlkList_Tail);
    }
    else if (to_size == 0) // 需要调整数据包的内存容量为0
    {
        packetBlock_free_list(packet_first_packetBlock(packet)); // 把数据包的整个数据块链表都释放出去
        packet->total_size = 0;
        list_init(&packet->block_list); // 重新初始化数据包的数据块链表
    }
    else if (to_size > packet->total_size) // 对数据包要进行扩大
    {
        D_PacketBlock *tail_block = packet_last_packetBlock(packet);
        int exploit_size = to_size - packet->total_size;     // 需要额外开拓的内存容量大小
        int remain_size = packetBlock_tail_free(tail_block); // 得到最后一个数据块剩余的内存空间容量
        if (remain_size >= exploit_size)
        {
            // 数据块剩余的空间大于等于开拓的空间容量，那就直接分配就可以了
            tail_block->size += exploit_size;
            packet->total_size += exploit_size;
        }
        else
        {
            // 需要额外分配数据块链表进行数据包内存空间拓展
            D_PacketBlock *new_blocks = packetBlock_alloc_list(exploit_size - remain_size, PacketBlock_Insertion_Tail); // 使用尾插法进行数据块链表的构建
            if (!new_blocks)
            {
                debug_error(Debug_Packet, "no block");
                return NET_ERR_MEMORY;
            }
            tail_block->size += remain_size;
            packet->total_size += remain_size;
            packet_insert_packetBlockList(packet, new_blocks, Packet_PacketBlkList_Tail); // 使用尾插法链接新的数据块链表
        }
    }
    else // 要对数据包的空间进行缩小
    {
        int total_size = 0;
        D_PacketBlock *tail_block;
        // 首先要定位到完成裁剪后的数据块链表的在最后一个
        for (tail_block = packet_first_packetBlock(packet); tail_block; tail_block = packetBlock_list_next(tail_block))
        {
            total_size += tail_block->size;
            if (total_size >= to_size)
            {
                break; // 只要数据包的容量大于等于需要的内存容量就直接退出
            }
        }
        if (tail_block == (D_PacketBlock *)0)
        {
            debug_error(Debug_Packet, "packet size err"); // 数据包的内存容量计算有误
            return NET_ERR_SIZE;
        }
        D_PacketBlock *current_block = packetBlock_list_next(tail_block); // 找到需要裁剪的第一个数据块链表的节点
        total_size = 0;
        while (current_block) // 把后续的数据块一个个移除
        {
            D_PacketBlock *next_block = packetBlock_list_next(current_block);
            total_size += current_block->size;
            list_remove_node(&packet->block_list, &current_block->node); // 从链表中移除该节点
            packetBlock_free(current_block);                             // 释放该数据块节点
            current_block = next_block;
        }
        tail_block->size -= packet->total_size - total_size - to_size; // 得到最后一个数据块的内存空间大小
        packet->total_size = to_size;
    }
    display_check_packet(packet);
    return NET_ERR_OK;
}

/***
 * @description: 把两个数据包进行合并(dest <- src)
 * @Author: Liverpool
 * @Date: 2024-03-31 17:31:32
 * @return {*} 数据包合并过程中的错误
 * @param {D_Packet} *dest 向用于存储合并数据包的目标数据包地址
 * @param {D_Packet} *src 要合并的数据包地址
 */
net_err_t packet_join(D_Packet *dest, D_Packet *src)
{
    debug_assert(dest->ref != 0, "packet ref == 0");
    debug_assert(src->ref != 0, "packet ref == 0");
    D_PacketBlock *first;
    // 遍历src的数据包中的数据块节点
    while ((first = packet_first_packetBlock(src)))
    {
        list_remove_first(&src->block_list);                                   // 移除第一个数据块链表的节点
        packet_insert_packetBlockList(dest, first, Packet_PacketBlkList_Tail); // 使用尾插法插入到目标数据块节点的后面
    }
    packet_free(src); // 释放src数据包
    display_check_packet(dest);
    return NET_ERR_OK;
}
/***
 * @description: 把数据包前面存储的固定尺寸的数据块链表调整为连续存储
 * @Author: Liverpool
 * @Date: 2024-04-02 02:49:33
 * @return {*} 在调整过程中发生的错误
 * @param {D_Packet} *packet 需要调整的数据包的内存地址
 * @param {int} size 需要设置成连续的前部容量大小
 */
net_err_t packet_set_continuous(D_Packet *packet, int size)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    // 1.首先对需要连续性操作的size进行判断
    if (size > packet->total_size)
    {
        // 调整包头的大小不能比整个数据包的容量大
        debug_error(Debug_Packet, "size %d > total_size %d", size, packet->total_size);
        return NET_ERR_SIZE;
    }
    if (size > Packet_PacketBlock_Size)
    {
        // 调整包头的size不能比整个数据块存储的最多容量还大
        debug_error(Debug_Packet, "size too big: %d > %d", size, Packet_PacketBlock_Size);
        return NET_ERR_SIZE;
    }
    // 2. 对在当前情况下是否需要调整包头结构进行判断
    D_PacketBlock *first_block = packet_first_packetBlock(packet);
    if (size < first_block->size)
    {
        // 如果第一个包头的连续性空间已经大于需要调整的空间，那就直接返回不需要再进行调整了
        display_check_packet(packet);
        return NET_ERR_OK;
    }
    // 3.真正开始对包头的固定尺寸进行连续化操作
    uint8_t *dest = first_block->payload; // 直接找到数据块缓存的初始位置
    // 对第一个块进行内存移植操作：从数据区的内存cope到数据块开头
    for (int i = 0; i < first_block->size; i++)
    {
        *dest++ = first_block->data[i];
    }
    first_block->data = first_block->payload;                       // 对数据存储位置移动到数据块开头
    int remain_size = size - first_block->size;                     // 得到还需要多少空间需要做连续性处理
    D_PacketBlock *curr_block = packetBlock_list_next(first_block); // 得到下一个数据块的地址
    while ((remain_size > 0) && curr_block)
    {
        // 计算这个数据块该处理的容量：在当前数据块容量和剩余的需要处理的容量中选取较小的值
        int curr_size = (curr_block->size > remain_size) ? remain_size : curr_block->size;
        plat_memcpy(dest, curr_block->data, curr_size); // 进行copy操作
        dest += curr_size;                              // 处理源copy地址
        first_block->size += curr_size;                 // 第一个节点加上copy的数据大小
        // 处理当前数据块的内容
        curr_block->data += curr_size;
        curr_block->size -= curr_size;
        remain_size -= curr_size; // 得到还需要处理的容量大小
        if (curr_block->size == 0)
        {
            // 如果当前的数据块中的所有内存容量都被copy走，那就需要删除该数据节点并且找到下一个数据块节点进行操作
            D_PacketBlock *next_block = packetBlock_list_next(curr_block);
            list_remove_node(&packet->block_list, &curr_block->node); // 在数据包的数据块链表中移除该空白节点
            packetBlock_free(curr_block);
            curr_block = next_block;
        }
    }
    display_check_packet(packet);
    return NET_ERR_OK;
}

/***
 * @description: 对数据包中的数据读写部分进行初始化(相当于文件打开功能)
 * @Author: Liverpool
 * @Date: 2024-04-03 02:05:34
 * @return {*}
 * @param {D_Packet} *packet
 */
void packet_reset_access(D_Packet *packet)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    if (packet)
    {
        packet->pos = 0;                                       // 起始位置为0
        packet->curr_block = packet_first_packetBlock(packet); // 指向第一个数据块节点
        packet->block_offset = packet->curr_block ? packet->curr_block->data : (uint8_t *)0;
    }
}
/***
 * @description: 根据需要移动的size对数据包的pos位置进行更新
 * @Author: Liverpool
 * @Date: 2024-04-11 01:27:53
 * @return {*}
 * @param {D_Packet} *packet 需要更新的数据包内存地址
 * @param {int} size 需要移动的尺寸
 */
static void packet_move_forward(D_Packet *packet, int size)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    // 对pos位置进行重新定位
    packet->pos += size;
    packet->block_offset += size;
    // 对pos位置的指向的数据块进行重新定位
    D_PacketBlock *curr_block = packet->curr_block;
    if (packet->block_offset >= curr_block->data + curr_block->size)
    {
        // 当前数据块的数据偏移位置已经大于数据块的存储空间，那就需要定位到下一个数据块
        packet->curr_block = packetBlock_list_next(curr_block);
        if (packet->curr_block)
        {
            packet->block_offset = packet->curr_block->data;
        }
        else
        {
            packet->block_offset = (uint8_t *)0;
        }
    }
}
/***
 * @description: 往数据包中写入固定长度的数据
 * @Author: Liverpool
 * @Date: 2024-04-09 20:21:47
 * @return {*}
 * @param {D_Packet} *packet 需要被写于的数据包的内存地址
 * @param {uint8_t} *src 需要写入数据的数据源
 * @param {int} size 需要写入的长度
 */
net_err_t packet_write(D_Packet *packet, uint8_t *src, int size)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    if (!src || size < 0)
    {
        return NET_ERR_PARAM;
    }
    int remain_size = total_packet_remain(packet);
    if (remain_size < size) // 数据包的剩余空间不足以写入当前的数据
    {
        debug_error(Debug_Packet, "size  error: %d < %d", remain_size, size);
        return NET_ERR_SIZE;
    }
    while (size)
    {
        int block_size = current_packet_packetBlock_remain(packet); // 得到当前数据块可以写入的剩余空间大小
        int copy_size = size > block_size ? block_size : size;      // 取其中的较小值
        plat_memcpy(packet->block_offset, src, copy_size);          // 进行数据的copy
        src += copy_size;
        size -= copy_size;
        packet_move_forward(packet, copy_size); // 移动pos位置
    }
    return NET_ERR_OK;
}

/***
 * @description: 从数据包中读取固定长度的数据
 * @Author: Liverpool
 * @Date: 2024-04-14 16:23:44
 * @return {*}
 * @param {D_Packet} *packet
 * @param {uint8_t} *dest
 * @param {int} size
 */
net_err_t packet_read(D_Packet *packet, uint8_t *dest, int size)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    if (!dest || size < 0)
    {
        return NET_ERR_PARAM;
    }
    int remain_size = total_packet_remain(packet);
    if (remain_size < size) // 数据包的剩余空间不足以读取当前的数据
    {
        debug_error(Debug_Packet, "size  error: %d < %d", remain_size, size);
        return NET_ERR_SIZE;
    }
    while (size)
    {
        int block_size = current_packet_packetBlock_remain(packet); // 得到当前数据块可以写入的剩余空间大小
        int copy_size = size > block_size ? block_size : size;      // 取其中的较小值
        plat_memcpy(dest, packet->block_offset, copy_size);         // 进行数据的copy
        dest += copy_size;
        size -= copy_size;
        packet_move_forward(packet, copy_size); // 移动pos位置
    }
    return NET_ERR_OK;
}

/***
 * @description: 在数据包定位pos指针
 * @Author: Liverpool
 * @Date: 2024-04-14 19:00:15
 * @return {*} 在定位过程中出现的错误
 * @param {D_Packet} *packet 需要重新定位的数据包地址
 * @param {int} offset  pos指针需要偏移的位置
 */
net_err_t packet_seek(D_Packet *packet, int offset)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    if (packet->pos == offset)
    {
        // 现在的偏移位置等于需要的偏移位置，那就直接返回
        return NET_ERR_OK;
    }
    // 偏移位置出现错误
    if ((offset < 0) || (offset >= packet->total_size))
    {
        return NET_ERR_SIZE;
    }
    // 分情况讨论偏移位置是否小于当前位置
    int move_bytes = 0; // 需要移动的字节数
    if (offset < packet->pos)
    {
        // 在当前pos位置往前找
        packet->curr_block = packet_first_packetBlock(packet);
        packet->block_offset = packet->curr_block->data;
        packet->pos = 0;
        move_bytes = offset;
    }
    else
    {
        // 从当前pos位置往后找
        move_bytes = offset - packet->pos;
    }
    //  进行pos移动定位
    while (move_bytes)
    {
        int remain_size = current_packet_packetBlock_remain(packet);
        int curr_move = move_bytes > remain_size ? remain_size : move_bytes; // 取较小的移动值
        packet_move_forward(packet, curr_move);
        move_bytes -= curr_move;
    }
    return NET_ERR_OK;
}
/***
 * @description: 两个数据包基于各自的pos位置进行数据内容的copy
 * @Author: Liverpool
 * @Date: 2024-04-14 20:58:38
 * @return {*} 在copy过程中出现的错误
 * @param {D_Packet} *dest 需要的copy的目标数据包内存地址
 * @param {D_Packet} *src 需要copy的源数据包内存地址
 * @param {int} size 需要copy的数据长度
 */
net_err_t packet_copy(D_Packet *dest, D_Packet *src, int size)
{
    debug_assert(dest->ref != 0, "packet ref == 0");
    debug_assert(src->ref != 0, "packet ref == 0");
    // 对数据包的容量进行判断
    if ((total_packet_remain(dest) < size) || (total_packet_remain(src) < size))
    {
        return NET_ERR_OK;
    }
    while (size)
    {
        // 得到两个数据包当前数据块剩余的数据存储空间
        int dest_remain = current_packet_packetBlock_remain(dest);
        int src_remain = current_packet_packetBlock_remain(src);
        // 取得较小值
        int copy_size = dest_remain > src_remain ? src_remain : dest_remain;
        copy_size = copy_size > size ? size : copy_size;
        // 进行数据复制
        plat_memcpy(dest->block_offset, src->block_offset, copy_size);
        packet_move_forward(dest, copy_size);
        packet_move_forward(src, copy_size);
        size -= copy_size;
    }
    return NET_ERR_OK;
}

/***
 * @description: 对数据包填充固定长度的数据
 * @Author: Liverpool
 * @Date: 2024-04-15 01:29:43
 * @return {*} 在填充过程中产生的错误
 * @param {D_Packet} *packet 需要进行填充的数据包内存地址
 * @param {uint8_t} value 进行数据填充的值
 * @param {int} size 需要填充的固定字节数
 */
net_err_t packet_fill(D_Packet *packet, uint8_t value, int size)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    if (size < 0)
    {
        return NET_ERR_PARAM;
    }
    int remain_size = total_packet_remain(packet);
    if (remain_size < size) // 数据包的剩余空间不足以写入当前的数据
    {
        debug_error(Debug_Packet, "size  error: %d < %d", remain_size, size);
        return NET_ERR_SIZE;
    }
    while (size)
    {
        int block_size = current_packet_packetBlock_remain(packet); // 得到当前数据块可以写入的剩余空间大小
        int fill_size = size > block_size ? block_size : size;      // 取其中的较小值
        plat_memset(packet->block_offset, value, fill_size);
        size -= fill_size;
        packet_move_forward(packet, fill_size); // 移动pos位置
    }
    return NET_ERR_OK;
}
/***
 * @description: 增加数据包的应用计数
 * @Author: Liverpool
 * @Date: 2024-04-16 01:53:29
 * @return {*}
 * @param {D_Packet} *packet 需要增加的数据包的内存地址
 */
void packet_inc_ref(D_Packet *packet)
{
    locker_lock(&locker);
    packet->ref++;
    locker_Unlock(&locker);
}

/***
 * @description: 对数据包进行16位的校验和计算(IP协议，TCP协议等使用)
 * @Author: Liverpool
 * @Date: 2024-07-11 15:12:50
 * @return {*} 返回最后的校验值
 * @param {D_Packet} *packet 需要校验的数据包内存地址
 * @param {int} len 需要校验的数据长度
 * @param {uint32_t} pre_sum 前数据报校验的校验值
 * @param {int} complement 校验值是否需要取反
 */
uint16_t packet_checksum_16(D_Packet *packet, int len, uint32_t pre_sum, int complement)
{
    debug_assert(packet->ref != 0, "packet ref == 0");
    int remain_size = total_packet_remain(packet); // 得到当前位置到数据包尾部的数据尺寸大小
    if (remain_size < len)
    {
        debug_Warning(Debug_Packet, "check data size too large...");
        return 0;
    }
    uint32_t sum = pre_sum;
    uint32_t offset = 0;
    // 对各个数据块做校验和计算处理
    while (len > 0)
    {
        int block_size = current_packet_packetBlock_remain(packet);            // 当前数据块剩余的空间大小
        int current_size = (block_size > len) ? len : block_size;              // 得到当前真正需要校验的数据长度大小(两者取小)
        sum = checksum_16(offset, packet->block_offset, current_size, sum, 0); // 进行校验和计算
        packet_move_forward(packet, current_size);                             // 数据进行前移
        len -= current_size;
        offset += current_size;
    }
    return complement ? (uint16_t)~sum : (uint16_t)sum;
}